import { zodResolver } from "@hookform/resolvers/zod";
import { motion } from "framer-motion";
import { useCallback, useMemo, useRef, useState } from "react";
import { useForm } from "react-hook-form";
import { z } from "zod";
import { useShallow } from "zustand/react/shallow";

import { LoadingAnimation } from "~/components/deer-flow/loading-animation";
import { Markdown } from "~/components/deer-flow/markdown";
import { RainbowText } from "~/components/deer-flow/rainbow-text";
import { RollingText } from "~/components/deer-flow/rolling-text";
import {
  ScrollContainer,
  type ScrollContainerRef,
} from "~/components/deer-flow/scroll-container";
import { Button } from "~/components/ui/button";
import {
  Card,
  CardContent,
  CardFooter,
  CardHeader,
  CardTitle,
} from "~/components/ui/card";
import {
  Form,
  FormControl,
  FormField,
  FormItem,
  FormLabel,
  FormMessage,
} from "~/components/ui/form";
import { Input } from "~/components/ui/input";
import MultipleFileUploader from "~/components/ui/multiple-file-uploader";
import { RadioGroup, RadioGroupItem } from "~/components/ui/radio-group";
import { Textarea } from "~/components/ui/textarea";
import { uploadInterview, type UploadInterviewParams } from "~/core/api/upload";
import type { Message, MessageRole, Option } from "~/core/messages";
import { InterviewStore } from "~/core/store";
import { parseJSON } from "~/core/utils";
import { cn } from "~/lib/utils";

export function MessageListView({
  className,
  onFeedback,
  onSendMessage,
}: {
  className?: string;
  onFeedback?: (feedback: { option: Option }) => void;
  onSendMessage: (
    message: string,
    options?: { role?: MessageRole; interruptFeedback?: string },
  ) => void;
}) {
  const scrollContainerRef = useRef<ScrollContainerRef>(null);
  const messageIds = InterviewStore.useMessageIds();
  const interruptMessage = InterviewStore.useLastInterruptMessage();
  const waitingForFeedbackMessageIds =
    InterviewStore.useLastFeedbackMessageIds();
  const responding = InterviewStore.useStore(
    useShallow((state) => state.responding),
  );
  // const hasOngoingMessage = InterviewStore.useStore(
  //   (state) => state.ongoingMessageId !== null,
  // );
  // const interviewPanelIsOpen = InterviewStore.useStore(
  //   (state) => state.interviewPanelIsOpen,
  // );

  // const handleToggleInterviewPanel = useCallback(() => {
  //   // Fix the issue where auto-scrolling to the bottom
  //   // occasionally fails when toggling research.
  //   const timer = setTimeout(() => {
  //     if (scrollContainerRef.current) {
  //       scrollContainerRef.current.scrollToBottom();
  //     }
  //   }, 500);
  //   return () => {
  //     clearTimeout(timer);
  //   };
  // }, []);

  return (
    <ScrollContainer
      className={cn("flex h-full w-full flex-col overflow-hidden", className)}
      scrollShadowColor="var(--app-background)"
      autoScrollToBottom
      ref={scrollContainerRef}
    >
      <ul className="flex flex-col">
        {messageIds.map((messageId) => (
          <MessageListItem
            key={messageId}
            messageId={messageId}
            waitForFeedback={waitingForFeedbackMessageIds.includes(messageId)}
            interruptMessage={interruptMessage}
            onFeedback={onFeedback}
            onSendMessage={onSendMessage}
          />
        ))}
        <div className="flex h-8 w-full shrink-0"></div>
      </ul>
      {responding && <LoadingAnimation className="ml-4" />}
    </ScrollContainer>
  );
}

function MessageListItem({
  className,
  messageId,
  waitForFeedback,
  interruptMessage,
  onFeedback,
  onSendMessage,
}: {
  className?: string;
  messageId: string;
  waitForFeedback?: boolean;
  onFeedback?: (feedback: { option: Option }) => void;
  interruptMessage?: Message | null;
  onSendMessage: (
    message: string,
    options?: { role?: MessageRole; interruptFeedback?: string },
  ) => void;
}) {
  const message = InterviewStore.useMessage(messageId);

  const researchStarted = InterviewStore.useStore(
    useShallow(
      (state) =>
        state.researcherMessageIds.length > 0 &&
        state.researcherMessageIds[0] === messageId,
    ),
  );

  const firstReporterMessageId = InterviewStore.useStore(
    useShallow((state) => state.firstReporterMessageId),
  );

  const jdGeneratorAcceptedMessageId = InterviewStore.useStore(
    useShallow((state) => state.jdGeneratorAcceptedMessageId),
  );

  const resumeMatcherAcceptedMessageId = InterviewStore.useStore(
    useShallow((state) => state.resumeMatcherAcceptedMessageId),
  );

  const questionGeneratorAcceptedMessageId = InterviewStore.useStore(
    useShallow((state) => state.questionGeneratorAcceptedMessageId),
  );

  const isBeginResumeMatcherMessageId = InterviewStore.useStore(
    useShallow((state) => state.resumeMatcherMessageIds.has(messageId)),
  );

  const isBeginQuestionGeneratorMessageId = InterviewStore.useStore(
    useShallow((state) => state.questionGeneratorMessageIds.has(messageId)),
  );

  const isBeginInterviewEvaluatorMessageId = InterviewStore.useStore(
    useShallow((state) => state.interviewEvaluatorMessageIds.has(messageId)),
  );

  const plannerHasEnoughContext = useMemo(() => {
    if (message?.agent === "planner") {
      return parseJSON(message.content ?? "", { has_enough_context: false })
        .has_enough_context;
    }
    return false;
  }, [message?.agent, message?.content]);

  if (message) {
    if (
      message.role === "user" ||
      message.agent === "coordinator" ||
      message.agent === "planner" ||
      message.agent === "reporter" ||
      message.agent === "jd_generator" ||
      message.agent === "resume_matcher" ||
      message.agent === "question_generator" ||
      message.agent === "interview_evaluator" ||
      researchStarted
    ) {
      let content: React.ReactNode;
      if (message.agent === "planner") {
        content = plannerHasEnoughContext ? null : (
          <div className="w-full px-4">
            <PlannerCard
              message={message}
              waitForFeedback={waitForFeedback}
              interruptMessage={interruptMessage}
              onFeedback={onFeedback}
              onSendMessage={onSendMessage}
            />
          </div>
        );
      } else if (researchStarted) {
        content = (
          <div className="w-full px-4">
            <ReporterCard
              messageId={firstReporterMessageId}
              onFeedback={onFeedback}
              onSendMessage={onSendMessage}
              waitForFeedback={waitForFeedback}
            />
          </div>
        );
      } else if (message.agent === "reporter") {
        if (firstReporterMessageId !== message.id) {
          content = (
            <div className="w-full px-4">
              <ReporterCard
                messageId={message.id}
                onFeedback={onFeedback}
                onSendMessage={onSendMessage}
                waitForFeedback={waitForFeedback}
              />
            </div>
          );
        }
      } else if (message.agent === "jd_generator") {
        content = (
          <>
            <div className="w-full px-4">
              <JdGeneratorCard
                messageId={message.id}
                onFeedback={onFeedback}
                waitForFeedback={
                  waitForFeedback && jdGeneratorAcceptedMessageId === null
                }
              />
            </div>
            {jdGeneratorAcceptedMessageId === message.id && (
              <div className="w-full px-4">
                <ResumeMatcherFormCard
                  className="mt-10"
                  onSendMessage={onSendMessage}
                />
              </div>
            )}
          </>
        );
      } else if (message.agent === "resume_matcher") {
        if (isBeginResumeMatcherMessageId) {
          content = (
            <>
              <div className="w-full px-4">
                <ResumeMatcherCard
                  messageId={message.id}
                  onFeedback={onFeedback}
                  waitForFeedback={
                    waitForFeedback && resumeMatcherAcceptedMessageId === null
                  }
                />
              </div>
              {resumeMatcherAcceptedMessageId === message.id && (
                <div className="w-full px-4">
                  <QuestionGeneratorFormCard
                    className="mt-10"
                    onSendMessage={onSendMessage}
                  />
                </div>
              )}
            </>
          );
        }
      } else if (message.agent === "question_generator") {
        if (isBeginQuestionGeneratorMessageId) {
          content = (
            <>
              <div className="w-full px-4">
                <QuestionGeneratorCard
                  messageId={message.id}
                  onFeedback={onFeedback}
                  waitForFeedback={
                    waitForFeedback &&
                    questionGeneratorAcceptedMessageId === null
                  }
                />
              </div>
              {questionGeneratorAcceptedMessageId === message.id && (
                <div className="w-full px-4">
                  <InterviewEvaluatorFormCard
                    className="mt-10"
                    onSendMessage={onSendMessage}
                  />
                </div>
              )}
            </>
          );
        }
      } else if (message.agent === "interview_evaluator") {
        if (isBeginInterviewEvaluatorMessageId) {
          content = (
            <div className="w-full px-4">
              <InterviewEvaluatorCard
                messageId={message.id}
                onFeedback={onFeedback}
                onSendMessage={onSendMessage}
                waitForFeedback={waitForFeedback}
              />
            </div>
          );
        }
      } else {
        content = message.content ? (
          <div
            className={cn(
              "flex w-full px-4",
              message.role === "user" && "justify-end",
              className,
            )}
          >
            <MessageBubble message={message}>
              <div className="flex w-full flex-col text-wrap break-words">
                <Markdown
                  className={cn(
                    message.role === "user" &&
                      "prose-invert not-dark:text-secondary dark:text-inherit",
                  )}
                >
                  {message?.content}
                </Markdown>
              </div>
            </MessageBubble>
          </div>
        ) : null;
      }
      if (content) {
        return (
          <motion.li
            className="mt-10"
            key={messageId}
            initial={{ opacity: 0, y: 24 }}
            animate={{ opacity: 1, y: 0 }}
            style={{ transition: "all 0.2s ease-out" }}
            transition={{
              duration: 0.2,
              ease: "easeOut",
            }}
          >
            {content}
          </motion.li>
        );
      }
    }
    return null;
  }
}

function MessageBubble({
  className,
  message,
  children,
}: {
  className?: string;
  message: Message;
  children: React.ReactNode;
}) {
  return (
    <div
      className={cn(
        `group flex w-fit max-w-[85%] flex-col rounded-2xl px-4 py-3 text-nowrap shadow`,
        message.role === "user" && "bg-brand rounded-ee-none",
        message.role === "assistant" && "bg-card rounded-es-none",
        className,
      )}
    >
      {children}
    </div>
  );
}

const GREETINGS = ["太棒了", "听起来不错", "看起来不错", "太好了", "很好"];

function PlannerCard({
  className,
  message,
  interruptMessage,
  onFeedback,
  waitForFeedback,
  onSendMessage,
}: {
  className?: string;
  message: Message;
  interruptMessage?: Message | null;
  onFeedback?: (feedback: { option: Option }) => void;
  onSendMessage?: (
    message: string,
    options?: { interruptFeedback?: string },
  ) => void;
  waitForFeedback?: boolean;
}) {
  const plan = useMemo<{
    title?: string;
    thought?: string;
    has_enough_context?: boolean;
    steps?: { title?: string; description?: string }[];
  }>(() => {
    return parseJSON(message.content ?? "", {});
  }, [message.content]);

  const title = useMemo(
    () =>
      `### ${
        plan.title !== undefined && plan.title !== ""
          ? plan.title
          : "深度研究中"
      }`,
    [plan],
  );

  const handleAccept = useCallback(async () => {
    if (onSendMessage) {
      onSendMessage(
        `${GREETINGS[Math.floor(Math.random() * GREETINGS.length)]}! ${Math.random() > 0.5 ? "让我们开始吧。" : "我们开始吧。"}`,
        {
          interruptFeedback: "accepted",
        },
      );
    }
  }, [onSendMessage]);

  return (
    <Card className={cn("w-full", className)}>
      <CardHeader>
        <CardTitle>
          <Markdown animated>{title}</Markdown>
        </CardTitle>
      </CardHeader>
      <CardContent>
        <Markdown className="opacity-80" animated>
          {plan.thought}
        </Markdown>
        {plan.steps && (
          <ul className="my-2 flex list-decimal flex-col gap-4 border-l-[2px] pl-8">
            {plan.steps.map((step, i) => (
              <li key={`step-${i}`}>
                <h3 className="mb text-lg font-medium">
                  <Markdown animated>{step.title}</Markdown>
                </h3>
                <div className="text-muted-foreground text-sm">
                  <Markdown animated>{step.description}</Markdown>
                </div>
              </li>
            ))}
          </ul>
        )}
      </CardContent>
      <CardFooter className="flex justify-end">
        {!message.isStreaming && interruptMessage && (
          <motion.div
            className="flex gap-2"
            initial={{ opacity: 0, y: 12 }}
            animate={{ opacity: 1, y: 0 }}
            transition={{ duration: 0.3, delay: 0.3 }}
          >
            {waitForFeedback && (
              <>
                <Button
                  variant="outline"
                  onClick={() => {
                    onFeedback?.({
                      option: { text: "编辑", value: "edit" },
                    });
                  }}
                >
                  编辑
                </Button>
                <Button
                  variant="default"
                  onClick={() => {
                    // accepted
                    void handleAccept();
                  }}
                >
                  开始评估
                </Button>
              </>
            )}
          </motion.div>
        )}
      </CardFooter>
    </Card>
  );
}

function ReporterCard({
  className,
  messageId,
  onFeedback,
  onSendMessage,
  waitForFeedback,
}: {
  className?: string;
  messageId?: string | null;
  onFeedback?: (feedback: { option: Option }) => void;
  onSendMessage?: (
    message: string,
    options?: { interruptFeedback?: string },
  ) => void;
  waitForFeedback?: boolean;
}) {
  const hasReport = messageId !== undefined;
  const generating = InterviewStore.useStore(
    useShallow((state) => {
      let generating = false;
      if (!messageId) {
        generating = true;
      } else if (messageId === state.firstReporterMessageId) {
        generating = messageId === state.ongoingMessageId;
      } else if (messageId === state.ongoingMessageId) {
        generating = true;
      }
      return generating;
    }),
  );
  const title = InterviewStore.useStore(
    useShallow((state) => {
      let title = null;
      for (let i = state.messageIds.length - 1; i > 0; i--) {
        const message = state.messages.get(state.messageIds[i]!);
        if (message?.agent === "planner") {
          title = parseJSON(message.content ?? "", { title: null }).title;
          break;
        }
      }
      return title;
    }),
  );

  const handleAccept = useCallback(async () => {
    if (onSendMessage) {
      onSendMessage(
        `${GREETINGS[Math.floor(Math.random() * GREETINGS.length)]}! ${Math.random() > 0.5 ? "让我们开始吧。" : "我们开始吧。"}`,
        {
          interruptFeedback: "accepted",
        },
      );
    }
  }, [onSendMessage]);

  return (
    <Card className={cn("w-full", className)}>
      <CardHeader>
        <CardTitle>
          <RainbowText animated={!hasReport}>
            {title ?? "深入研究中"}
          </RainbowText>
        </CardTitle>
      </CardHeader>
      <CardFooter>
        <div className="flex w-full">
          <RollingText className="text-muted-foreground flex-grow text-sm">
            {generating
              ? "报告生成中"
              : `报告${messageId === "none" ? "未" : "已"}生成`}
          </RollingText>
          <div className="flex gap-2">
            {waitForFeedback && (
              <>
                <Button
                  variant="outline"
                  onClick={() => {
                    onFeedback?.({
                      option: { text: "编辑", value: "edit" },
                    });
                  }}
                >
                  编辑
                </Button>
                <Button
                  variant="default"
                  onClick={() => {
                    // accepted
                    void handleAccept();
                  }}
                >
                  下一步
                </Button>
              </>
            )}
          </div>
        </div>
      </CardFooter>
    </Card>
  );
}

function JdGeneratorCard({
  className,
  messageId,
  onFeedback,
  waitForFeedback,
}: {
  className?: string;
  messageId: string;
  onFeedback?: (feedback: { option: Option }) => void;
  waitForFeedback?: boolean;
}) {
  const generating = InterviewStore.useStore(
    useShallow((state) => messageId === state.ongoingMessageId),
  );

  const handleAccept = useCallback(async () => {
    InterviewStore.setJdGeneratorAccepted(messageId);
  }, [messageId]);

  return (
    <Card className={cn("w-full", className)}>
      <CardHeader>
        <CardTitle>
          <RainbowText>JD生成</RainbowText>
        </CardTitle>
      </CardHeader>
      <CardFooter>
        <div className="flex w-full">
          <RollingText className="text-muted-foreground flex-grow text-sm">
            {generating ? "JD生成中" : "JD已生成"}
          </RollingText>
          <div className="flex gap-2">
            {waitForFeedback && (
              <>
                <Button
                  variant="outline"
                  onClick={() => {
                    onFeedback?.({
                      option: { text: "编辑", value: "edit" },
                    });
                  }}
                >
                  编辑
                </Button>
                <Button
                  variant="default"
                  onClick={() => {
                    // accepted
                    void handleAccept();
                  }}
                >
                  下一步
                </Button>
              </>
            )}
          </div>
        </div>
      </CardFooter>
    </Card>
  );
}

function ResumeMatcherFormCard({
  className,
  onSendMessage,
}: {
  className?: string;
  onSendMessage: (
    message: string,
    options?: { role?: MessageRole; interruptFeedback?: string },
  ) => void;
}) {
  const [submitted, setSubmitted] = useState<boolean>(false);
  const threadId = InterviewStore.useStore((state) => state.threadId);
  const uploadParams: UploadInterviewParams = useMemo(
    () => ({
      thread_id: threadId ?? "",
      agent_code: "interview",
      upload_type: "resume",
    }),
    [threadId],
  );

  const FormSchema = z.object({
    rule: z.string().optional(),
    resumesSource: z.enum(["file", "resume_repository", "boss"], {
      required_error: "请选择简历来源",
    }),
    resumes: z.array(z.any()).optional(), // FileWithPreview[] 类型
  });

  const form = useForm<z.infer<typeof FormSchema>>({
    resolver: zodResolver(FormSchema),
    defaultValues: {
      rule: "",
      resumesSource: "file",
      resumes: [],
    },
  });

  function onSubmit(data: z.infer<typeof FormSchema>) {
    if ((data.resumes?.length ?? 0) === 0) {
      form.setError("resumes", {
        type: "manual",
        message: "请上传简历",
      });
      return;
    }
    if (data.resumes?.some((r) => r.uploadStatus !== "success")) {
      form.setError("resumes", {
        type: "manual",
        message: "请等待文件上传/解析成功后在操作",
      });
      return;
    }
    onSendMessage(data.rule ?? "", {
      role: "form",
      interruptFeedback: "accepted",
    });
    setSubmitted(true);
  }

  return (
    <Card className={cn("w-full", className)}>
      <CardHeader>
        <CardTitle>简历匹配</CardTitle>
      </CardHeader>
      <CardContent>
        <Form {...form}>
          <form className="w-full space-y-6">
            <FormField
              control={form.control}
              name="rule"
              render={({ field }) => (
                <FormItem>
                  <FormLabel>筛选规则</FormLabel>
                  <FormControl>
                    <Textarea
                      placeholder="请输入筛选规则"
                      {...field}
                      disabled={submitted}
                    />
                  </FormControl>
                  <FormMessage />
                </FormItem>
              )}
            />
            <FormField
              control={form.control}
              name="resumesSource"
              render={({ field }) => (
                <FormItem className="space-y-3">
                  <FormControl>
                    <RadioGroup
                      onValueChange={field.onChange}
                      defaultValue={field.value}
                      className="flex flex-row"
                    >
                      <FormItem className="flex items-center gap-3">
                        <FormControl>
                          <RadioGroupItem value="file" disabled={submitted} />
                        </FormControl>
                        <FormLabel className="font-normal">本地上传</FormLabel>
                      </FormItem>
                      <FormItem className="flex items-center gap-3">
                        <FormControl>
                          <RadioGroupItem value="resumeRepository" disabled />
                        </FormControl>
                        <FormLabel className="font-normal">简历库</FormLabel>
                      </FormItem>
                      <FormItem className="flex items-center gap-3">
                        <FormControl>
                          <RadioGroupItem value="boss" disabled />
                        </FormControl>
                        <FormLabel className="font-normal">Boss 直聘</FormLabel>
                      </FormItem>
                    </RadioGroup>
                  </FormControl>
                  <FormMessage />
                </FormItem>
              )}
            />
            <FormField
              control={form.control}
              name="resumes"
              render={({ field }) => (
                <FormItem>
                  <FormControl>
                    <MultipleFileUploader
                      value={field.value}
                      onChange={field.onChange}
                      disabled={submitted}
                      accept=".txt,.pdf,.docx,.doc"
                      maxFiles={100}
                      maxSize={10 * 1024 * 1024} // 10MB
                      uploadFunction={uploadInterview}
                      uploadParams={uploadParams}
                    />
                  </FormControl>
                  <FormMessage />
                </FormItem>
              )}
            />
          </form>
        </Form>
      </CardContent>
      <CardFooter>
        <div className="flex w-full justify-end">
          <Button
            data-hidden={submitted}
            variant="default"
            className="self-end data-[hidden=true]:hidden"
            onClick={form.handleSubmit(onSubmit)}
          >
            下一步
          </Button>
        </div>
      </CardFooter>
    </Card>
  );
}

function ResumeMatcherCard({
  className,
  messageId,
  onFeedback,
  waitForFeedback,
}: {
  className?: string;
  messageId: string;
  onFeedback?: (feedback: { option: Option }) => void;
  waitForFeedback?: boolean;
}) {
  const generating = InterviewStore.useStore(
    (state) => messageId === state.ongoingMessageId,
  );

  const message = InterviewStore.useMessage(messageId);

  const title = useMemo(() => {
    if (message) {
      return parseJSON(message.content ?? "", { title: null }).title;
    }
    return undefined;
  }, [message]);

  const handleAccept = useCallback(async () => {
    InterviewStore.setResumeMatcherAccepted(messageId);
  }, [messageId]);

  return (
    <Card className={cn("w-full", className)}>
      <CardHeader>
        <CardTitle>
          <RainbowText>{title ?? "简历智能评估"}</RainbowText>
        </CardTitle>
      </CardHeader>
      <CardFooter>
        <div className="flex w-full">
          <RollingText className="text-muted-foreground flex-grow text-sm">
            {generating ? "简历评估中" : "简历评估完成"}
          </RollingText>
          <div className="flex gap-2">
            {waitForFeedback && (
              <>
                <Button
                  variant="outline"
                  onClick={() => {
                    onFeedback?.({
                      option: { text: "编辑", value: "edit" },
                    });
                  }}
                >
                  编辑
                </Button>
                <Button
                  variant="default"
                  onClick={() => {
                    // accepted
                    void handleAccept();
                  }}
                >
                  下一步
                </Button>
              </>
            )}
          </div>
        </div>
      </CardFooter>
    </Card>
  );
}

function QuestionGeneratorFormCard({
  className,
  onSendMessage,
}: {
  className?: string;
  onSendMessage: (
    message: string,
    options?: { role?: MessageRole; interruptFeedback?: string },
  ) => void;
}) {
  const [submitted, setSubmitted] = useState<boolean>(false);

  const FormSchema = z.object({
    type: z.enum(["all", "rank", "score", "other"], {
      required_error: "请选择筛选模式",
    }),
    rank: z.number().optional(),
    score: z.number().optional(),
    other: z.string().optional(),
  });

  const form = useForm<z.infer<typeof FormSchema>>({
    resolver: zodResolver(FormSchema),
    defaultValues: {
      type: "all",
      rank: 0,
      score: 0,
      other: "",
    },
  });

  function onSubmit(data: z.infer<typeof FormSchema>) {
    let message = "";

    // 验证逻辑
    if (data.type === "rank") {
      if (!data.rank) {
        form.setError("rank", {
          type: "manual",
          message: "请输入排名",
        });
        return;
      }
      message = `综合得分排名，前${data.rank}名`;
    } else if (data.type === "score") {
      if (!data.score) {
        form.setError("score", {
          type: "manual",
          message: "请输入综合得分",
        });
        return;
      }
      message = `综合得分，大于${data.score}分`;
    } else if (data.type === "other") {
      if (!data.other) {
        form.setError("other", {
          type: "manual",
          message: "请输入其它筛选条件",
        });
        return;
      }
      message = data.other ?? "";
    }

    onSendMessage(message, {
      role: "form",
      interruptFeedback: "accepted",
    });
    setSubmitted(true);
  }

  return (
    <Card className={cn("w-full", className)}>
      <CardHeader>
        <CardTitle>简历个性化面试问题生成</CardTitle>
      </CardHeader>
      <CardContent>
        <Form {...form}>
          <form className="w-full space-y-6">
            <FormField
              control={form.control}
              name="type"
              render={({ field }) => (
                <FormItem className="space-y-3">
                  <FormLabel>请先筛选简历</FormLabel>
                  <FormControl>
                    <RadioGroup
                      onValueChange={field.onChange}
                      defaultValue={field.value}
                      className="flex flex-col"
                      disabled={submitted}
                    >
                      <FormItem className="flex items-center gap-3">
                        <FormControl>
                          <RadioGroupItem value="all" />
                        </FormControl>
                        <FormLabel className="font-normal">全部简历</FormLabel>
                      </FormItem>
                      <FormItem className="flex items-center gap-3">
                        <FormControl>
                          <RadioGroupItem value="rank" />
                        </FormControl>
                        <FormLabel className="font-normal">
                          <span>综合得分排名，前</span>
                          <FormField
                            control={form.control}
                            name="rank"
                            render={({ field }) => (
                              <FormItem className="space-x-1">
                                <FormControl>
                                  <Input
                                    type="number"
                                    className="w-20"
                                    value={field.value ?? ""}
                                    disabled={submitted}
                                    onChange={(e) => {
                                      const value = e.target.value;
                                      field.onChange(
                                        value === ""
                                          ? undefined
                                          : Number(value),
                                      );
                                    }}
                                  />
                                </FormControl>
                                <FormMessage />
                              </FormItem>
                            )}
                          />
                          <span>名</span>
                        </FormLabel>
                      </FormItem>
                      <FormItem className="flex items-center gap-3">
                        <FormControl>
                          <RadioGroupItem value="score" />
                        </FormControl>
                        <FormLabel className="font-normal">
                          <span>综合得分，大于</span>
                          <FormField
                            control={form.control}
                            name="score"
                            render={({ field }) => (
                              <FormItem className="space-x-1">
                                <FormControl>
                                  <Input
                                    type="number"
                                    className="w-20"
                                    value={field.value ?? ""}
                                    disabled={submitted}
                                    onChange={(e) => {
                                      const value = e.target.value;
                                      field.onChange(
                                        value === ""
                                          ? undefined
                                          : Number(value),
                                      );
                                    }}
                                  />
                                </FormControl>
                                <FormMessage />
                              </FormItem>
                            )}
                          />
                          <span>分</span>
                        </FormLabel>
                      </FormItem>
                      <FormItem className="flex items-center gap-3">
                        <FormControl>
                          <RadioGroupItem value="other" />
                        </FormControl>
                        <FormLabel className="font-normal">
                          <span>其它</span>
                          <FormField
                            control={form.control}
                            name="other"
                            render={({ field }) => (
                              <FormItem className="space-x-1">
                                <FormControl>
                                  <Input
                                    type="text"
                                    className="w-40"
                                    disabled={submitted}
                                    {...field}
                                  />
                                </FormControl>
                                <FormMessage />
                              </FormItem>
                            )}
                          />
                        </FormLabel>
                      </FormItem>
                    </RadioGroup>
                  </FormControl>
                  <FormMessage />
                </FormItem>
              )}
            />
          </form>
        </Form>
      </CardContent>
      <CardFooter>
        <div className="flex w-full justify-end">
          <Button
            data-hidden={submitted}
            variant="default"
            className="self-end data-[hidden=true]:hidden"
            onClick={form.handleSubmit(onSubmit)}
          >
            下一步
          </Button>
        </div>
      </CardFooter>
    </Card>
  );
}

function QuestionGeneratorCard({
  className,
  messageId,
  onFeedback,
  waitForFeedback,
}: {
  className?: string;
  messageId: string;
  onFeedback?: (feedback: { option: Option }) => void;
  waitForFeedback?: boolean;
}) {
  const generating = InterviewStore.useStore(
    (state) => messageId === state.ongoingMessageId,
  );

  const handleAccept = useCallback(async () => {
    InterviewStore.setQuestionGeneratorAccepted(messageId);
  }, [messageId]);

  return (
    <Card className={cn("w-full", className)}>
      <CardHeader>
        <CardTitle>
          <RainbowText>简历面试问题生成</RainbowText>
        </CardTitle>
      </CardHeader>
      <CardFooter>
        <div className="flex w-full">
          <RollingText className="text-muted-foreground flex-grow text-sm">
            {generating ? "问题生成中" : "问题已生成"}
          </RollingText>
          <div className="flex gap-2">
            {waitForFeedback && (
              <>
                <Button
                  variant="outline"
                  onClick={() => {
                    onFeedback?.({
                      option: { text: "编辑", value: "edit" },
                    });
                  }}
                >
                  编辑
                </Button>
                <Button
                  variant="default"
                  onClick={() => {
                    // accepted
                    void handleAccept();
                  }}
                >
                  下一步
                </Button>
              </>
            )}
          </div>
        </div>
      </CardFooter>
    </Card>
  );
}

function InterviewEvaluatorFormCard({
  className,
  onSendMessage,
}: {
  className?: string;
  onSendMessage: (
    message: string,
    options?: { role?: MessageRole; interruptFeedback?: string },
  ) => void;
}) {
  const [submitted, setSubmitted] = useState<boolean>(false);
  const threadId = InterviewStore.useStore((state) => state.threadId);
  const uploadParams: UploadInterviewParams = useMemo(
    () => ({
      thread_id: threadId ?? "",
      agent_code: "interview",
      upload_type: "interview_record",
    }),
    [threadId],
  );

  const FormSchema = z.object({
    rule: z.string().optional(),
    files: z.array(z.any()).optional(),
  });

  const form = useForm<z.infer<typeof FormSchema>>({
    resolver: zodResolver(FormSchema),
    defaultValues: {
      rule: "",
      files: [],
    },
  });

  function onSubmit(data: z.infer<typeof FormSchema>) {
    if ((data.files?.length ?? 0) === 0) {
      form.setError("files", {
        type: "manual",
        message: "请上传面试记录",
      });
      return;
    }
    if (data.files?.some((r) => r.uploadStatus !== "success")) {
      form.setError("files", {
        type: "manual",
        message: "请等待文件上传/解析成功后在操作",
      });
      return;
    }
    onSendMessage(data.rule ?? "", {
      role: "form",
      interruptFeedback: "accepted",
    });
    setSubmitted(true);
  }

  return (
    <Card className={cn("w-full", className)}>
      <CardHeader>
        <CardTitle>面试评估打分</CardTitle>
      </CardHeader>
      <CardContent>
        <Form {...form}>
          <form className="w-full space-y-6">
            <FormField
              control={form.control}
              name="rule"
              render={({ field }) => (
                <FormItem>
                  <FormLabel>评分规则</FormLabel>
                  <FormControl>
                    <Textarea
                      placeholder="请输入评分规则"
                      {...field}
                      disabled={submitted}
                    />
                  </FormControl>
                  <FormMessage />
                </FormItem>
              )}
            />
            <FormField
              control={form.control}
              name="files"
              render={({ field }) => (
                <FormItem>
                  <FormControl>
                    <MultipleFileUploader
                      value={field.value}
                      onChange={field.onChange}
                      disabled={submitted}
                      accept=".txt,.pdf,.docx,.doc"
                      maxFiles={100}
                      maxSize={10 * 1024 * 1024} // 10MB
                      uploadFunction={uploadInterview}
                      uploadParams={uploadParams}
                    />
                  </FormControl>
                  <FormMessage />
                </FormItem>
              )}
            />
          </form>
        </Form>
      </CardContent>
      <CardFooter>
        <div className="flex w-full justify-end">
          <Button
            data-hidden={submitted}
            variant="default"
            className="self-end data-[hidden=true]:hidden"
            onClick={form.handleSubmit(onSubmit)}
          >
            下一步
          </Button>
        </div>
      </CardFooter>
    </Card>
  );
}

function InterviewEvaluatorCard({
  className,
  messageId,
  onFeedback,
  onSendMessage,
  waitForFeedback,
}: {
  className?: string;
  messageId: string;
  onFeedback?: (feedback: { option: Option }) => void;
  onSendMessage?: (
    message: string,
    options?: { interruptFeedback?: string },
  ) => void;
  waitForFeedback?: boolean;
}) {
  const generating = InterviewStore.useStore(
    (state) => messageId === state.ongoingMessageId,
  );

  const message = InterviewStore.useMessage(messageId);

  const title = useMemo(() => {
    if (message) {
      return parseJSON(message.content ?? "", { title: null }).title;
    }
    return undefined;
  }, [message]);

  const handleAccept = useCallback(async () => {
    if (onSendMessage) {
      onSendMessage(
        `${GREETINGS[Math.floor(Math.random() * GREETINGS.length)]}! ${Math.random() > 0.5 ? "让我们开始吧。" : "我们开始吧。"}`,
        {
          interruptFeedback: "accepted",
        },
      );
    }
  }, [onSendMessage]);
  return (
    <Card className={cn("w-full", className)}>
      <CardHeader>
        <CardTitle>
          <RainbowText>{title ?? "候选人面试评估报告"}</RainbowText>
        </CardTitle>
      </CardHeader>
      <CardFooter>
        <div className="flex w-full">
          <RollingText className="text-muted-foreground flex-grow text-sm">
            {generating ? "报告生成中" : "报告已生成"}
          </RollingText>
          <div className="flex gap-2">
            {waitForFeedback && (
              <>
                <Button
                  variant="outline"
                  onClick={() => {
                    onFeedback?.({
                      option: { text: "编辑", value: "edit" },
                    });
                  }}
                >
                  编辑
                </Button>
                <Button
                  variant="default"
                  onClick={() => {
                    // accepted
                    void handleAccept();
                  }}
                >
                  完成
                </Button>
              </>
            )}
          </div>
        </div>
      </CardFooter>
    </Card>
  );
}
